package topopt;

import fem2.AbstractStructuralStaticDemo;
import fem2.Constraint;
import fem2.Face;
import fem2.Force;
import fem2.Mesh;
import fem2.MeshUtilities;
import fem2.Model;
import fem2.Node;
import fem2.material.TopOptFilter;
import fem2.material.TopOptSensitivityFilter;

/**
 * simple topology optimization with 4 elements
 * 
 * @author hbui
 * 
 */
public class Simple2dTopOpt extends AbstractTopOptDemo {

	private double n1 = 3;
	private int n2 = 3;
	private double dx = 1.0;
	private double dy = 1.0;

	@Override
	public TopOptFilter createFilter(Model m) {
		double rmin = 1.5;
		TopOptFilter filter = new TopOptSensitivityFilter(m, rmin);
		return filter;
	}

	@Override
	public Mesh createMesh() {
		Mesh mesh = new Mesh();
		Node n1 = mesh.addNode(new Node(0, 2));
		Node n2 = mesh.addNode(new Node(0, 1));
		Node n3 = mesh.addNode(new Node(0, 0));
		Node n4 = mesh.addNode(new Node(1, 2));
		Node n5 = mesh.addNode(new Node(1, 1));
		Node n6 = mesh.addNode(new Node(1, 0));
		Node n7 = mesh.addNode(new Node(2, 2));
		Node n8 = mesh.addNode(new Node(2, 1));
		Node n9 = mesh.addNode(new Node(2, 0));
		mesh.addFace(new Face(n1, n2, n5, n4));
		mesh.addFace(new Face(n2, n3, n6, n5));
		mesh.addFace(new Face(n4, n5, n8, n7));
		mesh.addFace(new Face(n5, n6, n9, n8));

		return mesh;
	}

	@Override
	public Model createConditions(Model m) {
		Mesh mesh = m.getMesh();
		Constraint c1 = new Constraint(false, true);
		Constraint c2 = new Constraint(true, false);
		mesh.setConstraint(c1, MeshUtilities.seekNodesOnSurface(mesh, 1.0, 0.0, 0.0));
		MeshUtilities.seekNode(mesh, (n1 - 1) * dx, 0.0).setConstraint(c2);

		Node nf = MeshUtilities.seekNode(mesh, 0.0, (n2 - 1) * dy);
		double F = -1.0;
		Force f = new Force(nf, 0, F);
		m.addLoad(f);
		return m;
	}

	public static void main(String[] args) {
		AbstractStructuralStaticDemo demo = new Simple2dTopOpt();

		demo.run();
	}

}
